/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.constant.CommonConstant;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.domain.IsfdModelManagementCard;
import com.comac.ins.isfd.domain.bo.*;
import com.comac.ins.isfd.domain.vo.*;
import com.comac.ins.isfd.mapper.IsfdModelManagementCardMapper;
import com.comac.ins.isfd.service.IIsfdModelManagementCardService;
import com.comac.ins.isfd.service.IIsfdModelManagementPartService;
import com.comac.ins.isfd.util.RegexMatcher;
import com.comac.ins.isfd.util.CardUtils;
import com.comac.ins.isfd.util.SplitBDFFileIntoChunks;
import com.comac.ins.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

import static com.comac.ins.isfd.util.CreateGltfFromBDF.getBDFStats;

/**
 * ISFD模型管理单元卡Service业务层处理
 *
 * @author Lion Li
 * @date 2024-11-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class IsfdModelManagementCardServiceImpl implements IIsfdModelManagementCardService {

    @Autowired
    private IsfdModelManagementCardMapper baseMapper;

    @Autowired
    private IIsfdModelManagementPartService iIsfdModelManagementPartService;

    @Autowired
    private ISysDictDataService iSysDictDataService;

    /**
     * 查询ISFD模型管理单元卡
     *
     * @param id 主键
     * @return ISFD模型管理单元卡
     */
    @Override
    public IsfdModelManagementCardVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询ISFD模型管理单元卡列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return ISFD模型管理单元卡分页列表
     */
    @Override
    public TableDataInfo<IsfdModelManagementCardVo> queryPageList(IsfdModelManagementCardBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<IsfdModelManagementCard> lqw = buildQueryWrapper(bo, null);
        Page<IsfdModelManagementCardVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }


    private LambdaQueryWrapper<IsfdModelManagementCard> buildQueryWrapper(IsfdModelManagementCardBo bo, String place) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IsfdModelManagementCard> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getPartId() != null, IsfdModelManagementCard::getPartId, bo.getPartId());
        lqw.eq(StringUtils.isNotBlank(bo.getModelNumber()), IsfdModelManagementCard::getModelNumber, bo.getModelNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getSectionNumber()), IsfdModelManagementCard::getSectionNumber, bo.getSectionNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getComponentNumber()), IsfdModelManagementCard::getComponentNumber, bo.getComponentNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getPartNumber()), IsfdModelManagementCard::getPartNumber, bo.getPartNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getVersionNumber()), IsfdModelManagementCard::getVersionNumber, bo.getVersionNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getCardType()), IsfdModelManagementCard::getCardType, bo.getCardType());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), IsfdModelManagementCard::getType, bo.getType());
        lqw.eq(bo.getNumber() != null, IsfdModelManagementCard::getNumber, bo.getNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNumber()), IsfdModelManagementCard::getBatchNumber, bo.getBatchNumber());
        if (StringUtils.isNotBlank(place)) {
            lqw.and(lqw1 -> lqw1.eq(IsfdModelManagementCard::getPlace2, place)
                .or().eq(IsfdModelManagementCard::getPlace3, place)
                .or().eq(IsfdModelManagementCard::getPlace4, place)
                .or().eq(IsfdModelManagementCard::getPlace5, place)
                .or().eq(IsfdModelManagementCard::getPlace6, place)
                .or().eq(IsfdModelManagementCard::getPlace7, place));
        }
        lqw.orderByAsc(IsfdModelManagementCard::getNumber);
        return lqw;
    }

    @Override
    @Transactional
    public Boolean save(IsfdModelManagementCardSaveBo bo) {
        //1 校验
        String partPrePath = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
            CommonConstant.MODEL_MANAGEMENT_PART_DATA_PREFIX);
        if (com.comac.ins.common.core.utils.StringUtils.isBlank(partPrePath)) {
            log.error("字典中没有找到文件存储地址的相关配置。");
            throw new BaseException("字典中没有找到文件存储地址的相关配置。");
        }
        IsfdModelManagementCardVo isfdModelManagementCardVo = baseMapper.selectVoById(bo.getId());
        if (isfdModelManagementCardVo == null || !SplitBDFFileIntoChunks.P_SHELL.equals(isfdModelManagementCardVo.getCardType())) {
            log.error("单元卡不存在或当前单元卡不是pshell类型，请确认后重试！");
            throw new BaseException("单元卡不存在或当前单元卡不是pshell类型，请确认后重试！");
        }
        IsfdModelManagementPartVo isfdModelManagementPartVo = iIsfdModelManagementPartService.queryById(bo.getPartId());
        if (isfdModelManagementPartVo == null) {
            log.error("零件不存在，请确认后重试！");
            throw new BaseException("零件不存在，请确认后重试！");
        }
        IsfdModelManagementCardBo queryBo = new IsfdModelManagementCardBo();
        queryBo.setPartId(bo.getPartId());
        LambdaQueryWrapper<IsfdModelManagementCard> lqw = buildQueryWrapper(queryBo, null);
        List<IsfdModelManagementCardVo> cardVoList = baseMapper.selectVoList(lqw);
        if (CollectionUtils.isEmpty(cardVoList)) {
            log.error("单元卡列表不存在，请确认后重试！");
            throw new BaseException("单元卡列表不存在，请确认后重试！");
        }
        //2 写数据
        //2.1 写新零件db
        String brotherPartIndexPath = isfdModelManagementPartVo.getIndexPath();
        IsfdModelManagementPartBo partBo = MapstructUtils.convert(isfdModelManagementPartVo, IsfdModelManagementPartBo.class);
        String partName = isfdModelManagementPartVo.getPartNumber() + "_" + bo.getVersionNumber() + ".bdf";
        partBo.setFileName(partName);
        partBo.setPartName(partName);
        partBo.setVersionNumber(bo.getVersionNumber());
        partBo.setRemarks(bo.getRemarks());//新增的字段
        String indexPath = StringUtils.substringBeforeLast(brotherPartIndexPath, "/") + "/" + partName;
        partBo.setIndexPath(indexPath);
        partBo.setId(null);
        Long partId = iIsfdModelManagementPartService.insert(partBo);

        // 增加校验，place3必须能转为整数，place4必须能转为float或空
        String validatedPlace3 = CardUtils.validateIntegerPlace(bo.getPlace3());
        String validatedPlace4 = CardUtils.validateAndCorrectFloatPlace(bo.getPlace4());
        if (validatedPlace3 == null) {
            log.error("place3格式不符合要求！必须为整数！place3：{}", bo.getPlace3());
            throw new BaseException("place3格式不符合要求！必须为整数！place3："+ bo.getPlace3());
        }
        if (validatedPlace4 == null) {
            log.error("place4格式不符合要求！必须为浮点数！place4：{}", bo.getPlace4());
            throw new BaseException("place4格式不符合要求！必须为浮点数！place4：" + bo.getPlace4());
        }

        //2.2 写新单元卡db
        IsfdModelManagementCard targetPShell = new IsfdModelManagementCard();
        BeanUtils.copyProperties(isfdModelManagementCardVo, targetPShell);
        targetPShell.setPlace3(validatedPlace3);
        targetPShell.setPlace4(validatedPlace4);
        targetPShell.setVersionNumber(bo.getVersionNumber());
        targetPShell.setPartId(partId);

        // 批量封装数据，batches是最大容量是1000条
        List<List<IsfdModelManagementCard>> batches = new ArrayList<>();
        List<String> linesToWrite = new ArrayList<>();
        // 将CardVo列表转换为Card列表，并分批
        for (int i = 0; i < cardVoList.size(); i += 1000) {
            int end = Math.min(i + 1000, cardVoList.size());
            List<IsfdModelManagementCard> batch = new ArrayList<>();
            for (int j = i; j < end; j++) {
                IsfdModelManagementCardVo vo = cardVoList.get(j);
                IsfdModelManagementCard card = null;
                if (vo.getId().equals(targetPShell.getId())) {
                    card = targetPShell;
                } else {
                    card = new IsfdModelManagementCard();
                    BeanUtils.copyProperties(vo, card);
                    card.setPartId(partId);
                    card.setVersionNumber(partBo.getVersionNumber());
                }
                card.setId(null);
                batch.add(card);

                // 准备写入文件的行
                String line = buildFixedLengthLine(card);

                linesToWrite.add(line);
            }
            batches.add(batch);
        }

        // 批量新增
        for (List<IsfdModelManagementCard> batch : batches) {
            baseMapper.insertBatch(batch);
        }

        // 写入文件
        String filePath = RegexMatcher.getDataPath(partPrePath, isfdModelManagementPartVo.getBatchNumber(), indexPath);
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            for (String line : linesToWrite) {
                writer.write(line);
                writer.newLine();
            }
        } catch (Exception e) {
            log.error("写入文件失败", e);
            throw new BaseException("写入文件失败");
        }
        return Boolean.TRUE;
    }

    public static String buildFixedLengthLine(IsfdModelManagementCard card) {
        // 将所有 place 字段组成列表
        List<String> places = Arrays.asList(
            card.getPlace1(), card.getPlace2(), card.getPlace3(),
            card.getPlace4(), card.getPlace5(), card.getPlace6(),
            card.getPlace7(), card.getPlace8(), card.getPlace9(),
            card.getPlace10()
        );

        // 使用 StringBuilder 拼接结果
        StringBuilder lineBuilder = new StringBuilder();

        for (int i = 0; i < places.size(); i++) {
            // 处理每个字段
            String place = Optional.ofNullable(places.get(i)).orElse(""); // 如果为 null，则用空字符串替代
            String cleanedPlace = place.replace(" ", ""); // 移除字段中的所有空格

            // 检查长度
            if (cleanedPlace.length() > 8) {
                log.error("Place字段超过允许的长度，字段索引：{}，清理后内容：{}，长度：{}",
                    i + 1, cleanedPlace, cleanedPlace.length());
                throw new BaseException(String.format(
                    "Place字段超过允许的长度，字段索引：%d，清理后内容：%s，长度：%d",
                    i + 1, cleanedPlace, cleanedPlace.length()
                ));
            }

            // 补齐到 8 个字符
            String paddedPlace = String.format("%-8s", cleanedPlace);
            lineBuilder.append(paddedPlace); // 拼接到最终结果
        }

        // 返回最终结果字符串，长度固定为 80 个字符
        return lineBuilder.toString();
    }

    @Override
    public IsfdModelManagementCardSearchShowVo search(IsfdModelManagementCardSearchBo bo) {
        // 如果存在数据直接返回
        IsfdModelManagementCardBo queryBo = new IsfdModelManagementCardBo();
        queryBo.setPartId(bo.getPartId());
        queryBo.setCardType(bo.getCardType());
        LambdaQueryWrapper<IsfdModelManagementCard> lqw = buildQueryWrapper(queryBo, SplitBDFFileIntoChunks.completePlaceStr(bo.getPlace(), SplitBDFFileIntoChunks.LEFT));
        lqw.orderByAsc(IsfdModelManagementCard::getNumber); // 按照行数排序返回结果
        List<IsfdModelManagementCard> cardList = baseMapper.selectList(lqw);
        if (CollectionUtils.isEmpty(cardList)) {
            log.error("未查询到该单元卡类型相关数据！");
            throw new BaseException("未查询到该单元卡类型相关数据！");
        }
        // 构造返回信息
        IsfdModelManagementCardSearchShowVo searchShowVo = new IsfdModelManagementCardSearchShowVo();
        List<Long> matchNumberList = cardList.stream().map(IsfdModelManagementCard::getNumber).toList();
        searchShowVo.setMatchNumberList(matchNumberList);
        searchShowVo.setPartId(bo.getPartId());
        return searchShowVo;
    }

    @Override
    public IsfdModelManagementCardShowVo structCard(IsfdModelManagementCardStructBo bo) {
        // 查询零件是否存在
        IsfdModelManagementPartVo partVo = iIsfdModelManagementPartService.queryById(bo.getPartId());
        if (partVo == null) {
            log.error("未查询到相关零件！partId：{}", bo.getPartId());
            this.deletePart(bo.getPartId());
            throw new BaseException("未查询到相关零件！partId：" + bo.getPartId());
        }
        bo.setModelNumber(partVo.getModelNumber());
        bo.setBatchNumber(partVo.getBatchNumber());
        bo.setSectionNumber(partVo.getSectionNumber());
        bo.setComponentNumber(partVo.getComponentNumber());
        bo.setPartNumber(partVo.getPartNumber());
        bo.setVersionNumber(partVo.getVersionNumber());

        String classification = bo.getClassification();
        String prefix = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE, classification);

        // 零件中涉及的材料bdf地址
        String materialPath = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
            CommonConstant.MODEL_MANAGEMENT_MATERIAL_PATH);
        if (StringUtils.isBlank(prefix)) {
            log.error("未找到目录分类，请确认字典配置数据后重试！");
            throw new BaseException("未找到目录分类，请确认字典配置数据后重试！");
        }
        Path prefixPath = Paths.get(prefix);

        String uri = partVo.getIndexPath();
        Path uriPath = Paths.get(uri);

        // 确保前缀不重复
        Path targetPath = uriPath;
        if (!uriPath.startsWith(prefixPath)) {
            targetPath = Paths.get(RegexMatcher.getDataPath(prefix, partVo.getBatchNumber(), uri));
        }
        // 确保文件存在
        if (!Files.exists(targetPath)) {
            log.error("未找到文件！");
            throw new BaseException("未找到文件！");
        }
        // 调用python解析、获取卡片类型
        Map statsMap = getBDFStats(targetPath.toString(), materialPath);
        if (statsMap == null) {
            log.error("文件解析错误，文件路径：{}", targetPath.toString());
            throw new BaseException("文件解析错误，文件路径：" + targetPath.toString());
        }
        List<String> typesToProcess = getAllCards(statsMap);

        // 查询是否已结构化
        LambdaQueryWrapper<IsfdModelManagementCard> lqw = Wrappers.lambdaQuery();
        lqw.eq(IsfdModelManagementCard::getPartId, bo.getPartId());
        // 添加 type 不等于 '1' 的条件x`x
        lqw.ne(bo.getType() != null, IsfdModelManagementCard::getType, "1");
        // 添加排序条件
        lqw.orderByAsc(IsfdModelManagementCard::getNumber);
        List<IsfdModelManagementCard> cardList = baseMapper.selectList(lqw);
        if (cardList.isEmpty()) {
            // 当列表为空时，执行后续逻辑
            cardList = SplitBDFFileIntoChunks.processBDFFile(targetPath.toString(), typesToProcess, bo);
            this.insertCards(cardList);
        }
        // 对数据进行排序
        cardList.sort(Comparator.comparing(IsfdModelManagementCard::getNumber));
        // 组装返回数据
        IsfdModelManagementCardShowVo showVo = new IsfdModelManagementCardShowVo();
        showVo.setPartId(cardList.get(0).getPartId());
        showVo.setModelNumber(cardList.get(0).getModelNumber());
        showVo.setBatchNumber(cardList.get(0).getBatchNumber());
        showVo.setSectionNumber(cardList.get(0).getSectionNumber());
        showVo.setComponentNumber(cardList.get(0).getComponentNumber());
        showVo.setPartNumber(cardList.get(0).getPartNumber());
        showVo.setVersionNumber(cardList.get(0).getVersionNumber());
        List<IsfdModelManagementCardStructVo> cardStructVoList = MapstructUtils.convert(cardList, IsfdModelManagementCardStructVo.class);
        showVo.setCardList(cardStructVoList);
        showVo.setStatsMap(statsMap);
        return showVo;
    }

    private void insertCards(List<IsfdModelManagementCard> cardList) {
        // 每次插入的最大条数
        int batchSize = 1000;
        // 获取总的数据量
        int totalSize = cardList.size();
        // 根据 batchSize 分批插入
        for (int i = 0; i < totalSize; i += batchSize) {
            // 获取当前批次的结束索引
            int end = Math.min(i + batchSize, totalSize);
            // 获取当前批次的数据
            List<IsfdModelManagementCard> batchList = cardList.subList(i, end);
            // 调用 baseMapper 执行当前批次的插入
            baseMapper.insertBatch(batchList);
        }
    }

    private List<String> getAllCards(Map<String, List<Map<String, Object>>> map) {
        List<String> cards = new ArrayList<>();

        for (Map.Entry<String, List<Map<String, Object>>> entry : map.entrySet()) {
            String key = entry.getKey();
            List<Map<String, Object>> value = entry.getValue();

            for (Map<String, Object> item : value) {
                if (item.containsKey("card")) {
                    cards.add(item.get("card").toString());
                }
            }
        }

        return cards;
    }

    public Integer deletePart(Long partId) {
        List<IsfdModelManagementCard> cardList = baseMapper.selectList(Wrappers.<IsfdModelManagementCard>lambdaQuery()
            .eq(IsfdModelManagementCard::getPartId, partId));
        if (cardList.isEmpty()) {
            log.error("未找到相关零件卡片！partId: {}", partId);
            return 0;
        }
        return baseMapper.deleteBatchIds(cardList);
    }

}
